Istruzioni processore x86
Le seguenti tabelle sono per riferimento rapido: sono utili per la programmazione pratica, ma omettono molteplici dettagli che serve sapere, e che trovate nel resto del materiale.
Si ricorda che, nella sintassi GAS/AT&T, le istruzioni sono nel formato opcode source destination.
Nella colonna notazione, si indicano con [bwl]
le istruzioni che richiedono la specifica delle dimensioni.
Quando la dimensione è deducibile dai registri utilizzati, questi suffissi si possono omettere.
Per gli operandi, si indica con con r
un registro (come in mov %eax, %ebx
); con m
un indirizzo di memoria (immediato, come in mov numero, %eax
, o tramite registro, come in mov (%esi), %eax
, o ancora con indice, come in mov matrice(%esi, %ecx, 4)
); con i
un valore immediato (come in mov $0, %eax
).
Si ricorda che non tutte le combinazioni sono permesse nell'architettura x86: nessuna istruzione generale supporta l'indicazione di entrambi gli operandi in memoria (cioè, non si può scrivere movl x, y
o mov (%eax), (%ebx)
).
Fanno eccezione le istruzioni stringa come la movs
, usando operandi impliciti.
Spostamento di dati
Istruzione | Nome esteso | Notazione | Comportamento |
---|
mov | Move | mov[bwl] r/m/i, r/m | Scrive il valore sorgente nel destinatario. Non modifica ZF . |
lea | Load Effective Address | lea a, r | Scrive l'indirizzo nel registro destinatario. |
xchg | Exchange | xchg[bwl] r/m, r/m | Scambia il valore del sorgente con quello del destinatario. |
cbw | Convert Byte to Word | cbw | Estende il contenuto di %al su %ax , interpretandone il contenuto come intero. |
cwde | Convert Word to Doubleword | cwde | Estende il contenuto di %ax su %eax , interpretandone il contenuto come intero. |
push | Push onto the Stack | push[wl] r/m/i | Aggiunge il valore sorgente in cima allo stack (destinatario implicito). |
pop | Pop from the Stack | pop[wl] r/m | Rimuove un valore dallo stack (sorgente implicito) lo scrive nel destinatario. |
Aritmetica
Istruzione | Nome esteso | Notazione | Comportamento |
---|
add | Addition | add[bwl] r/m/i, r/m | Somma sorgente e destinatario, scrive il risultato sul destinatario. Valido sia per naturali che interi. Aggiorna CF e OF . |
sub | Subtraction | sub[bwl] r/m/i, r/m | Sottrae il sorgente dal destinatario, scrive il risultato sul destinatario. Valido sia per naturali che interi. Aggiorna CF e OF . |
adc | Addition with Carry | adc[bwl] r/m/i, r/m | Somma sorgente, destinatario e CF , scrive il risultato sul destinatario. Valido sia per naturali che interi. Aggiorna CF e OF . |
sbb | Subtraction with Borrow | sub[bwl] r/m/i, r/m | Sottrae il sorgente e CF dal destinatario, scrive il risultato sul destinatario. Valido sia per naturali che interi. Aggiorna CF e OF . |
inc | Increment | inc[bwl] r/m | Somma 1 (sorgente implicito) al destinatario. Non aggiorna CF . |
dec | Decrement | dec[bwl] r/m | Sottrae 1 (sorgente implicito) al destinatario. Non aggiorna CF . |
neg | Negation | neg[bwl] r/m | Sostituisce il destinatario con il suo opposto. Aggiorna OF . |
Le seguenti istruzioni hanno operandi e destinatari impliciti, che variano in base alla dimensione dell'operazione.
Usano in oltre composizioni di più registri: useremo %dx_%ax
per indicare un valore i cui bit più significativi sono scritti in %dx
e quelli meno significativi in %ax
.
Istruzione | Nome esteso | Notazione | Comportamento |
---|
mul | Unsigned Multiply, 8 bit | mulb r/m | Calcola su 16 bit il prodotto tra naturali del sorgente e %al , scrive il risultato su %ax . Se il risultato non è riducibile a 8 bit, mette CF e OF a 1, altrimenti a 0. |
mul | Unsigned Multiply, 16 bit | mulw r/m | Calcola su 32 bit il prodotto tra naturali del sorgente e %ax , scrive il risultato su %dx_%ax . Se il risultato non è riducibile a 16 bit, mette CF e OF a 1, altrimenti a 0. |
mul | Unsigned Multiply, 32 bit | mull r/m | Calcola su 64 bit il prodotto tra naturali del sorgente e %eax , scrive il risultato su %edx_%eax . Se il risultato non è riducibile a 32 bit, mette CF e OF a 1, altrimenti a 0. |
imul | Signed Multiply, 8 bit | imulb r/m | Calcola su 16 bit il prodotto tra interi del sorgente e %al , scrive il risultato su %ax . Se il risultato non è riducibile a 8 bit, mette CF e OF a 1, altrimenti a 0. |
imul | Signed Multiply, 16 bit | imulw r/m | Calcola su 32 bit il prodotto tra interi del sorgente e %ax , scrive il risultato su %dx_%ax . Se il risultato non è riducibile a 16 bit, mette CF e OF a 1, altrimenti a 0. |
imul | Signed Multiply, 32 bit | imull r/m | Calcola su 64 bit il prodotto tra interi del sorgente e %eax , scrive il risultato su %edx_%eax . Se il risultato non è riducibile a 32 bit, mette CF e OF a 1, altrimenti a 0. |
Istruzione | Nome esteso | Notazione | Comportamento |
---|
div | Unsigned Divide, 8 bit | divb r/m | Calcola su 8 bit la divisione tra naturali tra %ax (dividendo implicito) e il sorgento (divisore). Scrive il quoziente su %al e il resto su %ah . Se il quoziente non è rappresentabile su 8 bit, causa crash del programma. |
div | Unsigned Divide, 16 bit | divw r/m | Calcola su 16 bit la divisione tra naturali tra %dx_%ax (dividendo implicito) e il sorgento (divisore). Scrive il quoziente su %ax e il resto su %dx . Se il quoziente non è rappresentabile su 16 bit, causa crash del programma. |
div | Unsigned Divide, 32 bit | divl r/m | Calcola su 32 bit la divisione tra naturali tra %edx_%eax (dividendo implicito) e il sorgento (divisore). Scrive il quoziente su %eax e il resto su %edx . Se il quoziente non è rappresentabile su 32 bit, causa crash del programma. |
idiv | Signed Divide, 8 bit | idivb r/m | Calcola su 8 bit la divisione tra interi tra %ax (dividendo implicito) e il sorgento (divisore). Scrive il quoziente su %al e il resto su %ah . Se il quoziente non è rappresentabile su 8 bit, causa crash del programma. |
idiv | Signed Divide, 16 bit | idivw r/m | Calcola su 16 bit la divisione tra interi tra %dx_%ax (dividendo implicito) e il sorgento (divisore). Scrive il quoziente su %ax e il resto su %dx . Se il quoziente non è rappresentabile su 16 bit, causa crash del programma. |
idiv | Signed Divide, 32 bit | idivl r/m | Calcola su 32 bit la divisione tra interi tra %edx_%eax (dividendo implicito) e il sorgento (divisore). Scrive il quoziente su %eax e il resto su %edx . Se il quoziente non è rappresentabile su 32 bit, causa crash del programma. |
Logica binaria
Le seguenti istruzioni operano bit a bit: data per esempio la and
, l'i-esimo bit del risultato è l'and logico tra gli i-esimi bit di sorgente e destinatario.
Istruzione | Notazione | Comportamento |
---|
not | not[bwl] r/m | Sostituisce il destinatario con la sua negazione. |
and | and r/m/i, r/m | Calcola l'and logico tra sorgente e destinatario, scrive il risultato sul destinatario. |
or | or r/m/i, r/m | Calcola l'or logico tra sorgente e destinatario, scrive il risultato sul destinatario. |
xor | xor r/m/i, r/m | Calcola lo xor logico tra sorgente e destinatario, scrive il risultato sul destinatario. |
Traslazione e Rotazione
Istruzione | Nome esteso | Notazione | Comportamento |
---|
shl | Shift Logical Left | shl[bwl] i/r r/m | Sia n l'operando sorgente, esegue lo shift a sinistra del destinatario n volte. In ciascuno shift, il bit più significativo viene lasciato in CF . Come registro sorgente si può utilizzare solo %cl . Il sorgente può essere omesso, in quel caso n=1. |
sal | Shift Arithmetic Left | sal[bwl] i/r r/m | Sia n l'operando sorgente, esegue lo shift a sinistra del destinatario n volte. Se il bit più significativo ha cambiato valore almeno una volta, imposta OF a 1. Come registro sorgente si può utilizzare solo %cl . Il sorgente può essere omesso, in quel caso n=1. |
shr | Shift Logical Right | shr[bwl] i/r r/m | Sia n l'operando sorgente, esegue lo shift a destra del destinatario n volte, impostando a 0 gli n bit più significativi. In ciascuno shift, il bit più significativo viene lasciato in CF . Come registro sorgente si può utilizzare solo %cl . Il sorgente può essere omesso, in quel caso n=1. |
sar | Shift Arithmetic Right | sar[bwl] i/r r/m | Sia n l'operando sorgente e s il valore del bit più significativo del destinatario, esegue lo shift a destra del destinatario n volte, impostando a s gli n bit più significativi. Il bit più significativo tra quelli rimossi viene lasciato in CF . Come registro sorgente si può utilizzare solo %cl . Il sorgente può essere omesso, in quel caso n=1. |
rol | Rotate Left | rol[bwl] i/r r/m | Sia n l'operando sorgente, esegue la rotazione a sinistra del destinatario n volte. In ciascuna rotazione, il bit più significativo viene sia lasciato in CF sia ricopiato al posto del bit meno significativo. Come registro sorgente si può utilizzare solo %cl . Il sorgente può essere omesso, in quel caso n=1. |
ror | Rotate Right | ror[bwl] i/r r/m | Sia n l'operando sorgente, esegue la rotazione a destra del destinatario n volte. In ciascuna rotazione, il bit meno significativo viene sia lasciato in CF sia ricopiato al posto del bit più significativo. Come registro sorgente si può utilizzare solo %cl . Il sorgente può essere omesso, in quel caso n=1. |
rcl | Rotate with Carry Left | rcl[bwl] i/r r/m | Sia n l'operando sorgente, esegue la rotazione con carry a sinistra del destinatario n volte. In ciascuna rotazione, il bit più significativo viene lasciato in CF , mentre il valore di CF viene ricopiato al posto del bit meno significativo. Come registro sorgente si può utilizzare solo %cl . Il sorgente può essere omesso, in quel caso n=1. |
rcr | Rotate with Carry Right | rcr[bwl] i/r r/m | Sia n l'operando sorgente, esegue la rotazione con carry a destra del destinatario n volte. In ciascuna rotazione, il bit meno significativo viene lasciato in CF , mentre il valore di CF viene ricopiato al posto del bit più significativo. Come registro sorgente si può utilizzare solo %cl . Il sorgente può essere omesso, in quel caso n=1. |
Controllo di flusso
Istruzione | Nome esteso | Notazione | Comportamento |
---|
jmp | Unconditional Jump | jmp m/r | Salta incondizionatamente all'indirizzo specificato. |
call | Call Procedure | call m/r | Chiamata a procedura all'indirizzo specificato. Salva l'indirizzo della prossima istruzione nello stack, così che il flusso corrente possa essere ripreso con una ret . |
ret | Return from Procedure | ret | Ritorna ad un flusso di esecuzione precedente, rimuovendo dallo stack l'indirizzo precedentemente salvato da una call . |
La tabella seguente elenca i salti condizionati.
I salti condizionati usano i flag per determinare se la condizione di salto è vera.
Per un uso sempre coerente, assicurarsi che l'istruzione di salto segua immediatamente una cmp
, o altre istruzioni che non hanno modificano i flag dopo la cmp
.
Dati gli operandi della cmp
ed una condizione c, per esempio c = "maggiore o uguale", la condizione è vera se destinatario c sorgente.
Nella tabella che segue, quando ci si riferisce ad un confronto fra sorgente e destinatario si intendono gli operandi della cmp
precedente.
Istruzione | Nome esteso | Notazione | Comportamento |
---|
cmp | Compare Two Operands | cmp[bwl] r/m/i, r/m | Confronta i due operandi e aggiorna i flag di conseguenza. |
je | Jump if Equal | je m | Salta se destinatario == sorgente. |
jne | Jump if Not Equal | jne m | Salta se destinatario != sorgente. |
ja | Jump if Above | ja m | Salta se, interpretandoli come naturali, destinatario > sorgente. |
jae | Jump if Above or Equal | jae m | Salta se, interpretandoli come naturali, destinatario >= sorgente. |
jb | Jump if Below | jb m | Salta se, interpretandoli come naturali, destinatario < sorgente. |
jbe | Jump if Below or Equal | jbe m | Salta se, interpretandoli come naturali, destinatario <= sorgente. |
jg | Jump if Greater | jg m | Salta se, interpretandoli come interi, destinatario > sorgente. |
jge | Jump if Greater or Equal | jge m | Salta se, interpretandoli come interi, destinatario >= sorgente. |
jl | Jump if Less | jl m | Salta se, interpretandoli come interi, destinatario < sorgente. |
jle | Jump if Less or Equal | jle m | Salta se, interpretandoli come interi, destinatario <= sorgente. |
jz | Jump if Zero | jz m | Salta se ZF è 1. |
jnz | Jump if Not Zero | jnz m | Salta se ZF è 0. |
jc | Jump if Carry | jc m | Salta se CF è 1. |
jnc | Jump if Not Carry | jnc m | Salta se CF è 0. |
jo | Jump if Overflow | jo m | Salta se OF è 1. |
jno | Jump if Not Overflow | jno m | Salta se OF è 0. |
js | Jump if Sign | js m | Salta se SF è 1. |
jns | Jump if Not Sign | jns m | Salta se SF è 0. |
Operazioni condizionali
Per alcune operazioni tipiche, sono disponibili istruzioni specifiche il cui comportamento dipende dai flag e, quindi, dal risultato di una precedente cmp
.
Anche qui, quando ci si riferisce ad un confronto fra sorgente e destinatario si intendono gli operandi della cmp
precedente.
La famiglia di istruzioni loop
supportano i cicli condizionati più tipici.
Rimangono d'interesse didattico come istruzioni specializzate ma, curiosamente, nei processori moderni sono generalmente meno performanti degli equivalenti che usino dec
,cmp
e salti condizionati.
Istruzione | Nome esteso | Notazione | Comportamento |
---|
loop | Unconditional Loop | loop m | Decrementa %ecx e salta se il risultato è (ancora) diverso da 0. |
loope | Loop if Equal | loope m | Decrementa %ecx e salta se entrambe le condizioni sono vere: 1)%ecx è (ancora) diverso da 0, 2) destinatario == sorgente. |
loopne | Loop if Not Equal | loopne m | Decrementa %ecx e salta se entrambe le condizioni sono vere: 1)%ecx è (ancora) diverso da 0, 2) destinatario != sorgente. |
loopz | Loop if Zero | loopz m | Decrementa %ecx e salta se entrambe le condizioni sono vere: 1)%ecx è (ancora) diverso da 0, 2) ZF è 1. |
loopnz | Loop if Not Zero | loopnz m | Decrementa %ecx e salta se entrambe le condizioni sono vere: 1)%ecx è (ancora) diverso da 0, 2) ZF è 0. |
La famiglia di istruzioni set
permettono di salvare il valore di un confronto in un registro o locazione di memoria.
Tale operando può essere solo da 1 byte.
Istruzione | Nome esteso | Notazione | Comportamento |
---|
sete | Set if Equal | sete r/m | Imposta l'operando a 1 se destinatario == sorgente, a 0 altrimenti. |
setne | Set if Not Equal | setne r/m | Imposta l'operando a 1 se destinatario != sorgente, a 0 altrimenti. |
seta | Set if Above | seta r/m | Imposta l'operando a 1 se, interpretandoli come naturali, destinatario > sorgente, a 0 altrimenti. |
setae | Set if Above or Equal | setae r/m | Imposta l'operando a 1 se, interpretandoli come naturali, destinatario >= sorgente, a 0 altrimenti. |
setb | Set if Below | setb r/m | Imposta l'operando a 1 se, interpretandoli come naturali, destinatario < sorgente, a 0 altrimenti. |
setbe | Set if Below or Equal | setbe r/m | Imposta l'operando a 1 se, interpretandoli come naturali, destinatario <= sorgente, a 0 altrimenti. |
setg | Set if Greater | setg r/m | Imposta l'operando a 1 se, interpretandoli come interi, destinatario > sorgente, a 0 altrimenti. |
setge | Set if Greater or Equal | setge r/m | Imposta l'operando a 1 se, interpretandoli come interi, destinatario >= sorgente, a 0 altrimenti. |
setl | Set if Less | setl r/m | Imposta l'operando a 1 se, interpretandoli come interi, destinatario < sorgente, a 0 altrimenti. |
setle | Set if Less or Equal | setle r/m | Imposta l'operando a 1 se, interpretandoli come interi, destinatario <= sorgente, a 0 altrimenti. |
setz | Set if Zero | setz r/m | Imposta l'operando a 1 se ZF è 1, a 0 altrimenti. |
setnz | Set if Not Zero | setnz r/m | Imposta l'operando a 1 se ZF è 0, a 0 altrimenti. |
setc | Set if Carry | setc r/m | Imposta l'operando a 1 se CF è 1, a 0 altrimenti. |
setnc | Set if Not Carry | setnc r/m | Imposta l'operando a 1 se CF è 0, a 0 altrimenti. |
seto | Set if Overflow | seto r/m | Imposta l'operando a 1 se OF è 1, a 0 altrimenti. |
setno | Set if Not Overflow | setno r/m | Imposta l'operando a 1 se OF è 0, a 0 altrimenti. |
sets | Set if Sign | sets r/m | Imposta l'operando a 1 se SF è 1, a 0 altrimenti. |
setns | Set if Not Sign | setns r/m | Imposta l'operando a 1 se SF è 0, a 0 altrimenti. |
Istruzione | Nome esteso | Notazione | Comportamento |
---|
cmove | Move if Equal | cmove r/m r | Esegue la mov se destinatario == sorgente, altrimenti non fa nulla. |
cmovne | Move if Not Equal | cmovne r/m | Esegue la mov se destinatario != sorgente, altrimenti non fa nulla. |
cmova | Move if Above | cmova r/m | Esegue la mov se, interpretandoli come naturali, destinatario > sorgente, altrimenti non fa nulla. |
cmovae | Move if Above or Equal | cmovae r/m | Esegue la mov se, interpretandoli come naturali, destinatario >= sorgente, altrimenti non fa nulla. |
cmovb | Move if Below | cmovb r/m | Esegue la mov se, interpretandoli come naturali, destinatario < sorgente, altrimenti non fa nulla. |
cmovbe | Move if Below or Equal | cmovbe r/m | Esegue la mov se, interpretandoli come naturali, destinatario <= sorgente, altrimenti non fa nulla. |
cmovg | Move if Greater | cmovg r/m | Esegue la mov se, interpretandoli come interi, destinatario > sorgente, altrimenti non fa nulla. |
cmovge | Move if Greater or Equal | cmovge r/m | Esegue la mov se, interpretandoli come interi, destinatario >= sorgente, altrimenti non fa nulla. |
cmovl | Move if Less | cmovl r/m | Esegue la mov se, interpretandoli come interi, destinatario < sorgente, altrimenti non fa nulla. |
cmovle | Move if Less or Equal | cmovle r/m | Esegue la mov se, interpretandoli come interi, destinatario <= sorgente, altrimenti non fa nulla. |
cmovz | Move if Zero | cmovz r/m | Esegue la mov se ZF è 1, altrimenti non fa nulla. |
cmovnz | Move if Not Zero | cmovnz r/m | Esegue la mov se ZF è 0, altrimenti non fa nulla. |
cmovc | Move if Carry | cmovc r/m | Esegue la mov se CF è 1, altrimenti non fa nulla. |
cmovnc | Move if Not Carry | cmovnc r/m | Esegue la mov se CF è 0, altrimenti non fa nulla. |
cmovo | Move if Overflow | cmovo r/m | Esegue la mov se OF è 1, altrimenti non fa nulla. |
cmovno | Move if Not Overflow | cmovno r/m | Esegue la mov se OF è 0, altrimenti non fa nulla. |
cmovs | Move if Sign | cmovs r/m | Esegue la mov se SF è 1, altrimenti non fa nulla. |
cmovns | Move if Not Sign | cmovns r/m | Esegue la mov se SF è 0, altrimenti non fa nulla. |
Istruzioni stringa
Le istruzioni stringa sono ottimizzate per eseguire operazioni tipiche su vettori in memoria.
Hanno esclusivamente operandi impliciti, che rende la specifica delle dimensioni non opzionale.
Istruzione | Nome esteso | Notazione | Comportamento |
---|
cld | Clear Direction Flag | cld | Imposta DF a 0, implicando che le istruzioni stringa procederanno per indirizzi crescenti. |
std | Set Direction Flag | std | Imposta DF a 1, implicando che le istruzioni stringa procederanno per indirizzi decrescenti. |
lods | Load String | lods[bwl] | Legge 1/2/4 byte all'indirizzo in %esi e lo scrive in %al /%ax /%eax . Se DF è 0, incrementa %esi di 1/2/4, se è 1 lo decrementa. |
stos | Store String | stos[bwl] | Legge il valore in %al /%ax /%eax e lo scrive nei 1/2/4 byte all'indirizzo in %edi . Se DF è 0, incrementa %edi di 1/2/4, se è 1 lo decrementa. |
movs | Move String to String | movs[bwl] | Legge 1/2/4 byte all'indirizzo in %esi e lo scrive nei 1/2/4 byte all'indirizzo in %edi . Se DF è 0, incrementa %edi di 1/2/4, se è 1 lo decrementa. |
cmps | Compare Strings | cmps[bwl] | Confronta gli 1/2/4 byte all'indirizzo in %esi (sorgente) con quelli all'indirizzo in %edi (destinatario). Aggiorna i flag così come fa cmp . |
scas | Scan String | scas[bwl] | Confronta %al /%ax /%eax (sorgente) con gli 1/2/4 byte all'indirizzo in %edi (destinatario). Aggiorna i flag così come fa cmp . |
Repeat Instruction
Le istruzioni stringa possono essere ripetute senza controllo di programma, usando il prefisso rep
.
Istruzione | Nome esteso | Notazione | Comportamento |
---|
rep | Unconditional Repeat Instruction | rep [opcode] | Dato n il valore in %ecx , ripete l'operazione opcode n volte, decrementando %ecx fino a 0. Compatibile con lods , stos , movs . |
repe | Repeat Instruction if Equal | repe [opcode] | Dato n il valore in %ecx , decrementa %ecx e ripete l'operazione opcode finché 1) %ecx è (ancora) diverso da 0, e 2) gli operandi di questa ripetizione erano uguali. Compatibile con cmps e scas . |
repne | Repeat Instruction if Not Equal | repne [opcode] | Dato n il valore in %ecx , decrementa %ecx e ripete l'operazione opcode finché 1) %ecx è (ancora) diverso da 0, e 2) gli operandi di questa ripetizione erano disuguali. Compatibile con cmps e scas . |
Altre istruzioni
Istruzione | Nome esteso | Notazione | Comportamento |
---|
nop | No Operation | nop | Non cambia lo stato del processore in alcun modo, eccetto per il registro %eip . |
Le seguenti istruzioni sono di interesse didattico ma non per le esercitazioni, in quanto richiedono privilegi di esecuzione.
Istruzione | Nome esteso | Notazione | Comportamento |
---|
in | Input from Port | in r/i r | Legge da una porta di input ad un registro. |
out | Output to Port | out r r/i | Scrive da un registro ad una porta di output. |
ins | Input String from Port | ins[bwl] | Legge 1/2/4 byte dalla porta di input indicata in %dx e li scrive nei 1/2/4 byte all'indirizzo in %edi . |
outs | Output String to Port | outs[bwl] | Legge 1/2/4 byte all'indirizzo indicato da %esi e li scrive alla porta di output indicata in %dx . |
hlt | Halt | hlt | Blocca ogni operazione del processore. |